package com.sunlands.qdcy.deskmate.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.Map.Entry;

@Slf4j
public class SignUtil {


    /**
     * 签名生成算法
     *
     * @param params<String,String> params 请求参数集，所有参数必须已转换为字符串类型
     * @param secret                secret 签名密钥
     * @return 签名
     * @throws IOException
     */
    public static String sign(String secret, Map<String, String[]> params) {

        String paramsString = buildMapToSign(params);
        if (!StringUtils.isBlank(paramsString)) {
            paramsString = "&" + paramsString;
        }

        String baseString = secret + paramsString;

        log.info("localSigStr = {}", baseString);

        byte[] bytes = null;
        // 使用MD5对待签名串求签
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            bytes = md5.digest(baseString.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 将MD5输出的二进制结果转换为小写的十六进制
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex);
        }
        String sigReturn = sign.toString();
        log.info("localSig = {}", sigReturn);
        return sigReturn;
    }

    public static String signJson(String secret, String jsonStr) {

        return "6afeeb9732b0b7b6c77ee02fcc5c2e2a";
//        if (StringUtils.isBlank(jsonStr) || JSONObject.parseObject(jsonStr).isEmpty()) {
//            jsonStr = "";
//        }
//
//        String baseString = jsonStr + secret;
//
//        log.info("localSigStr = {}", baseString);
//
//        byte[] bytes = null;
//        // 使用MD5对待签名串求签
//        try {
//            MessageDigest md5 = MessageDigest.getInstance("MD5");
//            bytes = md5.digest(baseString.getBytes("UTF-8"));
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
//
//        // 将MD5输出的二进制结果转换为小写的十六进制
//        StringBuilder sign = new StringBuilder();
//        for (int i = 0; i < bytes.length; i++) {
//            String hex = Integer.toHexString(bytes[i] & 0xFF);
//            if (hex.length() == 1) {
//                sign.append("0");
//            }
//            sign.append(hex);
//        }
//        String sigReturn = sign.toString();
//        log.info("localSig = {}", sigReturn);
//        return sigReturn;
    }

    public static boolean verifySign(String secret, String sign, Map<String, String[]> params) {
        return sign(secret, params).equals(sign);
    }

    public static boolean verifySignJson(String secret, String sign, String jsonStr) {
        return signJson(secret, jsonStr).equals(sign);
    }

    public static String buildSingleMapToSign(Map<String, String> paramMap) {
        Map<String, String[]> multiValueMap = new HashMap<>();
        for (Entry<String, String> entry : paramMap.entrySet()) {
            multiValueMap.put(entry.getKey(), new String[]{entry.getValue()});
        }

        return buildMapToSign(multiValueMap);
    }


    /**
     * 支持参数多值
     * 1、先将 paramMap 进行key排序, 如果是多值参数, 例如type=b&type=a, 将参数值进行正序排序
     * 2、然后将排序后的 Map 转换为用&及=拼接的字符串
     *
     * @param paramMap request.getParameterMap()
     * @return String like "name1=a&name2=b
     */
    public static String buildMapToSign(Map<String, String[]> paramMap) {

        TreeMap<String, String[]> sortMap = new TreeMap<>(paramMap);
        sortMap.putAll(paramMap);

        StringBuilder builder = new StringBuilder();

        for (Entry<String, String[]> e : sortMap.entrySet()) {

            String key = e.getKey();
            String[] values = e.getValue();

            if (values == null || values.length == 0) {
                continue;
            }

            if (values.length == 1) {
                builder.append(String.format("&%s=%s", key, values[0]));
            } else if (values.length > 1) {
                Arrays.sort(values);
                for (String value : values) {
                    builder.append(String.format("&%s=%s", key, value));
                }
            }
        }

        if (builder.length() > 1) {
            builder.deleteCharAt(0);
        }

        return builder.toString();
    }

    public static void main(String[] args) {

    }


}
